package com.tiniplanet.webgate.dao.hibernate;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.criterion.Projections;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Transactional;

import com.tiniplanet.webgate.dao.BaseDao;

@Transactional
public class BaseDaoImpl<T, Id extends Serializable> extends HibernateDaoSupport
		implements BaseDao<T, Id>, Serializable {

	private static final long serialVersionUID = -8317439112223262870L;

	private static final Logger logger = Logger.getLogger(BaseDaoImpl.class);

	private Class<T> type;

	public BaseDaoImpl(Class<T> type) {
		this.type = type;
	}

	@Override
	public T getById(Id id) {
		return getHibernateTemplate().get(type, id);
	}

	@Override
	public List<T> getAll() {
		return getHibernateTemplate().loadAll(type);
	}

	@Override
	public void save(T entity) {
		getHibernateTemplate().update(entity);
	}

	@Override
	public void delete(T entity) {
		getHibernateTemplate().delete(entity);
	}

	@Override
	public void deleteById(Id id) {
		getHibernateTemplate().delete(getById(id));
	}

	@Override
	public void add(T entity) {
		getHibernateTemplate().save(entity);
	}

	@Override
	public boolean isExist(T entity) {
		return getHibernateTemplate().contains(entity);
	}

	@Override
	public long count() {
		return (Long) getSession().createCriteria(type).setProjection(Projections.rowCount()).uniqueResult();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> get(int from, int to) {
		ClassMetadata classMeta = getSessionFactory().getClassMetadata(type);
		logger.debug("Get from " + from + " to " + to + " of table " + classMeta.getEntityName());
		Query query = getSession().createQuery("from " + classMeta.getEntityName() + " o");
		query.setFirstResult(from);
		query.setMaxResults(to - from);
		List<T> result = query.list();
		return result;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> getPage(int pageId, int pageSize, String sortedBy) {
		int from = (pageId - 1) * pageSize;
		int to = pageId * pageSize;

		if (StringUtils.isEmpty(sortedBy)) {
			return get(from, to);
		} else {
			ClassMetadata classMeta = getSessionFactory().getClassMetadata(type);
			logger.debug("Get from " + from + " to " + to + " of table " + classMeta.getEntityName());
			Query query = getSession().createQuery("from " + classMeta.getEntityName() + " order by " + sortedBy);

			query.setFirstResult(from);
			query.setMaxResults(to - from);
			List<T> result = query.list();
			return result;
		}
	}

}